from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem, 
                           QHBoxLayout, QHeaderView, QAbstractItemView, QComboBox, QPushButton, 
                           QGridLayout, QGroupBox, QLineEdit, QCheckBox)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIntValidator
from utils import format_hex_with_space, format_vc_frame_count
from frame_processor import FrameProcessor

class PlotWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.layout = QVBoxLayout()
        self.frames = []  # 存储所有帧数据
        
        # 分页控制变量
        self.current_page = 1
        self.page_size = 100  # 每页显示帧数
        self.total_pages = 1
        self.show_error_frames_first = True  # 优先显示错误帧
        self.filtered_frames = []  # 筛选后的帧数据（用于分页显示）

        # 设置表格通用样式
        self.setStyleSheet("""
            QTableWidget {
                gridline-color: #DDDDDD;
                background-color: white;
                alternate-background-color: #E3F2FD;  /* 浅蓝色背景 */
                selection-background-color: #2196F3;  /* 选中时的深蓝色 */
                selection-color: white;
            }
            QHeaderView::section {
                background-color: #1976D2;  /* 深蓝色表头背景 */
                color: white;  /* 表头文字颜色 */
                padding: 6px;
                border: none;
                font-weight: bold;
            }
            QHeaderView::section:checked {
                background-color: #1565C0;  /* 选中时更深的蓝色 */
            }
            QGroupBox {
                border: 1px solid #BBBBBB;
                border-radius: 5px;
                margin-top: 10px;
                padding-top: 12px;
                font-weight: bold;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                subcontrol-position: top center;
                padding: 0 5px;
            }
        """)

        # 创建总体信息显示区域
        self.info_group = QGridLayout()

        # 总帧数显示
        self.total_frames_label = QLabel()
        self.total_frames_label.setStyleSheet("QLabel { font-size: 12pt; font-weight: bold; }")

        self.info_group.addWidget(QLabel("总体统计："), 0, 0)
        self.info_group.addWidget(self.total_frames_label, 0, 1)

        # 创建原始数据表格
        self.raw_data_group = QGroupBox("原始帧数据")
        self.raw_data_layout = QVBoxLayout()
        self.raw_data_group.setLayout(self.raw_data_layout)

        # 添加分页控制区域
        pagination_widget = QWidget()
        pagination_layout = QHBoxLayout(pagination_widget)
        pagination_layout.setContentsMargins(0, 0, 0, 5)
        
        # 优先显示错误帧选项
        self.error_first_checkbox = QCheckBox("优先显示错误帧")
        self.error_first_checkbox.setChecked(True)
        self.error_first_checkbox.toggled.connect(self._on_error_first_toggled)
        pagination_layout.addWidget(self.error_first_checkbox)
        
        # 每页显示数量选择
        pagination_layout.addWidget(QLabel("每页显示:"))
        self.page_size_combo = QComboBox()
        self.page_size_combo.addItems(["20", "50", "100", "200", "500"])
        self.page_size_combo.setCurrentText("100")
        self.page_size_combo.currentTextChanged.connect(self._on_page_size_changed)
        pagination_layout.addWidget(self.page_size_combo)
        
        # 页码控制
        pagination_layout.addStretch()
        self.prev_page_btn = QPushButton("上一页")
        self.prev_page_btn.setEnabled(False)
        self.prev_page_btn.clicked.connect(self._on_prev_page)
        pagination_layout.addWidget(self.prev_page_btn)
        
        self.page_info_label = QLabel("第 1 / 1 页")
        pagination_layout.addWidget(self.page_info_label)
        
        self.next_page_btn = QPushButton("下一页")
        self.next_page_btn.setEnabled(False)
        self.next_page_btn.clicked.connect(self._on_next_page)
        pagination_layout.addWidget(self.next_page_btn)
        
        # 跳转到页功能
        pagination_layout.addStretch()
        pagination_layout.addWidget(QLabel("跳转到:"))
        self.goto_page_input = QLineEdit()
        self.goto_page_input.setFixedWidth(50)
        self.goto_page_input.setValidator(QIntValidator(1, 9999))
        pagination_layout.addWidget(self.goto_page_input)
        self.goto_page_btn = QPushButton("确定")
        self.goto_page_btn.clicked.connect(self._on_goto_page)
        pagination_layout.addWidget(self.goto_page_btn)
        
        # 添加分页控件到布局
        self.raw_data_layout.addWidget(pagination_widget)

        self.raw_data_table = QTableWidget()
        self.raw_data_table.setColumnCount(4)
        self.raw_data_table.setHorizontalHeaderLabels([
            '帧序号',
            '虚拟信道帧计数',
            '虚拟信道',
            '译码状态'
        ])
        # 设置表格为不可编辑状态
        self.raw_data_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 设置表格属性以适应内容
        self.raw_data_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.raw_data_table.horizontalHeader().setStretchLastSection(True)
        self.raw_data_table.setHorizontalScrollMode(QTableWidget.ScrollPerPixel)
        # 启用交替行颜色
        self.raw_data_table.setAlternatingRowColors(True)
        self.raw_data_layout.addWidget(self.raw_data_table)

        # 创建表格布局
        self.tables_layout = QGridLayout()

        # 创建虚拟信道表格
        self.vc_table = QTableWidget()
        self.vc_table.setColumnCount(3)
        self.vc_table.setHorizontalHeaderLabels([
            '虚拟信道',
            '帧数量',
            '占比'
        ])
        # 设置表格为不可编辑状态
        self.vc_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.vc_table.setMinimumHeight(200)
        # 设置表格属性以适应内容
        self.vc_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.vc_table.horizontalHeader().setStretchLastSection(True)
        self.vc_table.setHorizontalScrollMode(QTableWidget.ScrollPerPixel)
        # 启用交替行颜色
        self.vc_table.setAlternatingRowColors(True)

        # 创建译码状态表格
        self.status_table = QTableWidget()
        self.status_table.setColumnCount(3)
        self.status_table.setHorizontalHeaderLabels(['译码状态', '数量', '占比'])
        # 设置表格为不可编辑状态
        self.status_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.status_table.setMinimumHeight(150)
        # 设置表格属性以适应内容
        self.status_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.status_table.horizontalHeader().setStretchLastSection(True)
        self.status_table.setHorizontalScrollMode(QTableWidget.ScrollPerPixel)
        # 启用交替行颜色
        self.status_table.setAlternatingRowColors(True)

        # 添加表格说明标签
        self.vc_label = QLabel("虚拟信道统计：")
        self.vc_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.status_label = QLabel("译码状态统计：")
        self.status_label.setStyleSheet("QLabel { font-weight: bold; }")

        # 添加表格到布局
        self.tables_layout.addWidget(self.vc_label, 0, 0)
        self.tables_layout.addWidget(self.vc_table, 1, 0)
        self.tables_layout.addWidget(self.status_label, 0, 1)
        self.tables_layout.addWidget(self.status_table, 1, 1)

        # 创建帧计数连续性统计表格
        self.continuity_label = QLabel("帧计数连续性统计：")
        self.continuity_label.setStyleSheet("QLabel { font-weight: bold; }")
        
        # 创建连续性统计组框
        self.continuity_group = QGroupBox()
        self.continuity_layout = QVBoxLayout()
        self.continuity_group.setLayout(self.continuity_layout)
        
        # 连续性统计的分页控制
        continuity_pagination_widget = QWidget()
        continuity_pagination_layout = QHBoxLayout(continuity_pagination_widget)
        continuity_pagination_layout.setContentsMargins(0, 0, 0, 5)
        
        # 每页显示数量选择
        continuity_pagination_layout.addWidget(QLabel("每页显示:"))
        self.continuity_page_size_combo = QComboBox()
        self.continuity_page_size_combo.addItems(["10", "20", "50", "100"])
        self.continuity_page_size_combo.setCurrentText("20")
        self.continuity_page_size_combo.currentTextChanged.connect(self._on_continuity_page_size_changed)
        continuity_pagination_layout.addWidget(self.continuity_page_size_combo)
        
        # 页码控制
        continuity_pagination_layout.addStretch()
        self.continuity_prev_page_btn = QPushButton("上一页")
        self.continuity_prev_page_btn.setEnabled(False)
        self.continuity_prev_page_btn.clicked.connect(self._on_continuity_prev_page)
        continuity_pagination_layout.addWidget(self.continuity_prev_page_btn)
        
        self.continuity_page_info_label = QLabel("第 1 / 1 页")
        continuity_pagination_layout.addWidget(self.continuity_page_info_label)
        
        self.continuity_next_page_btn = QPushButton("下一页")
        self.continuity_next_page_btn.setEnabled(False)
        self.continuity_next_page_btn.clicked.connect(self._on_continuity_next_page)
        continuity_pagination_layout.addWidget(self.continuity_next_page_btn)
        
        # 添加分页控件到布局
        self.continuity_layout.addWidget(continuity_pagination_widget)
        
        # 创建连续性统计表格
        self.continuity_table = QTableWidget()
        self.continuity_table.setColumnCount(5)
        self.continuity_table.setHorizontalHeaderLabels([
            '位置索引',
            '前一帧计数',
            '当前帧计数',
            '期望帧计数',
            '虚拟信道'
        ])
        # 设置表格为不可编辑状态
        self.continuity_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.continuity_table.setMinimumHeight(200)
        # 设置表格属性以适应内容
        self.continuity_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.continuity_table.horizontalHeader().setStretchLastSection(True)
        self.continuity_table.setHorizontalScrollMode(QTableWidget.ScrollPerPixel)
        # 启用交替行颜色
        self.continuity_table.setAlternatingRowColors(True)
        self.continuity_layout.addWidget(self.continuity_table)
        
        # 连续性统计相关变量
        self.continuity_info = None
        self.continuity_current_page = 1
        self.continuity_page_size = 20
        self.continuity_total_pages = 1

        # 添加详细统计信息区域
        self.stats_label = QLabel("详细统计信息：")
        self.stats_label.setStyleSheet("QLabel { font-weight: bold; }")
        self.stats_text = QLabel()
        self.stats_text.setWordWrap(True)
        self.stats_text.setStyleSheet("QLabel { font-size: 10pt; }")

        # 默认隐藏详细统计信息区域
        self.stats_label.hide()
        self.stats_text.hide()

        # 将所有组件添加到主布局
        self.layout.addLayout(self.info_group)
        self.layout.addWidget(self.raw_data_group)
        self.layout.addLayout(self.tables_layout)
        self.layout.addWidget(self.continuity_label)
        self.layout.addWidget(self.continuity_group)
        self.layout.addWidget(self.stats_label)
        self.layout.addWidget(self.stats_text)

        self.setLayout(self.layout)
        
    def set_frames(self, frames):
        """设置帧数据并更新显示"""
        self.frames = frames
        self.update_pagination()
        self._update_table_display()
        
    def update_pagination(self):
        """更新分页信息"""
        # 应用过滤器（如果需要优先显示错误帧）
        self._apply_frame_filter()
        
        # 计算总页数
        self.total_pages = (len(self.filtered_frames) + self.page_size - 1) // self.page_size
        if self.total_pages == 0:
            self.total_pages = 1
            
        # 确保当前页在有效范围内
        if self.current_page > self.total_pages:
            self.current_page = 1
            
        # 更新页码信息显示
        self._update_pagination_controls()
    
    def _apply_frame_filter(self):
        """应用帧过滤，实现优先显示错误帧"""
        # 如果没有帧数据，直接返回空列表
        if not self.frames:
            self.filtered_frames = []
            return
            
        # 如果需要优先显示错误帧
        if self.show_error_frames_first:
            # 分离错误帧和正常帧
            error_frames = []
            normal_frames = []
            
            for frame in self.frames:
                # 检查是否为错误帧（根据译码状态和帧检验结果判断）
                is_error = False
                
                # 获取译码状态位
                decode_status = frame['decode_status']
                frame_check_result = frame.get('帧检验结果', 0)
                
                # RS译码开启（Bit0=1）
                if decode_status & 0x01:
                    rs_error_bit = (frame_check_result >> 24) & 0x01
                    if rs_error_bit == 1:  # RS译码错误
                        is_error = True
                
                # LDPC译码开启（Bit4=1）
                if (decode_status >> 4) & 0x01:
                    ldpc_status_byte = (frame_check_result >> 24) & 0xFF
                    if ldpc_status_byte == 0x01 or ldpc_status_byte == 0x02:  # LDPC译码失败或帧校验错误
                        is_error = True
                
                # 根据错误状态添加到相应列表
                if is_error:
                    error_frames.append(frame)
                else:
                    normal_frames.append(frame)
            
            # 合并列表，错误帧在前
            self.filtered_frames = error_frames + normal_frames
        else:
            # 不需要特殊排序，直接使用原始顺序
            self.filtered_frames = self.frames.copy()
    
    def _update_pagination_controls(self):
        """更新分页控件状态"""
        self.page_info_label.setText(f"第 {self.current_page} / {self.total_pages} 页")
        self.prev_page_btn.setEnabled(self.current_page > 1)
        self.next_page_btn.setEnabled(self.current_page < self.total_pages)
    
    def _on_page_size_changed(self, text):
        """处理每页显示数量变化"""
        try:
            self.page_size = int(text)
            self.current_page = 1  # 重置到第一页
            self.update_pagination()
            self._update_table_display()
        except ValueError:
            pass  # 忽略无效输入
    
    def _on_prev_page(self):
        """前一页按钮点击处理"""
        if self.current_page > 1:
            self.current_page -= 1
            self._update_pagination_controls()
            self._update_table_display()
    
    def _on_next_page(self):
        """下一页按钮点击处理"""
        if self.current_page < self.total_pages:
            self.current_page += 1
            self._update_pagination_controls()
            self._update_table_display()
    
    def _on_goto_page(self):
        """跳转到指定页处理"""
        try:
            page = int(self.goto_page_input.text())
            if 1 <= page <= self.total_pages:
                self.current_page = page
                self._update_pagination_controls()
                self._update_table_display()
                # 清空输入框
                self.goto_page_input.clear()
        except ValueError:
            pass  # 忽略无效输入
    
    def _on_error_first_toggled(self, checked):
        """处理优先显示错误帧选项变化"""
        self.show_error_frames_first = checked
        self.current_page = 1  # 重置到第一页
        self.update_pagination()
        self._update_table_display()
    
    def _update_table_display(self):
        """更新表格显示当前页的帧数据"""
        # 计算当前页显示的帧范围
        start_idx = (self.current_page - 1) * self.page_size
        end_idx = min(start_idx + self.page_size, len(self.filtered_frames))
        
        # 获取当前页要显示的帧
        display_frames = self.filtered_frames[start_idx:end_idx]
        
        # 设置表格行数
        self.raw_data_table.setRowCount(len(display_frames))
        
        # 填充表格数据
        for i, frame in enumerate(display_frames):
            # 计算原始索引（在未过滤列表中的位置）
            original_idx = self.frames.index(frame) if frame in self.frames else i
            
            # 帧序号 - 显示原始索引
            self.raw_data_table.setItem(i, 0, QTableWidgetItem(str(original_idx + 1)))
            
            # 虚拟信道帧计数 - 优先使用payload[6:9]提取的值
            vc_count = FrameProcessor.extract_virtual_channel_frame_count(frame)
            if vc_count == 0:
                # 如果提取失败，则回退到frame['frame_count']的低3字节
                vc_count = frame['frame_count'] & 0xFFFFFF
            self.raw_data_table.setItem(i, 1, QTableWidgetItem(format_vc_frame_count(vc_count)))
            
            # 虚拟信道
            self.raw_data_table.setItem(i, 2, QTableWidgetItem(f"VC{frame['virtual_channel']}"))
            
            # 译码状态说明
            status = frame['decode_status']
            frame_check_decode = frame['decode_status']
            
            # 尝试获取帧检验结果
            frame_check_result = frame.get('帧检验结果', 0)
            
            status_text = []
            
            # 获取帧检验&译码状态的Bit 0和Bit 4
            bit0_value = frame_check_decode & 0x01
            bit4_value = (frame_check_decode >> 4) & 0x01
            
            if frame_check_decode == 0:
                status_text.append("无R-S译码")
            else:
                # 当RS译码开启时（Bit0=1），检查RS译码正确性
                if bit0_value == 1:
                    rs_error_bit = (frame_check_result >> 24) & 0x01  # 获取Byte0的bit0
                    if rs_error_bit == 0:
                        status_text.append("RS译码正确")
                    elif rs_error_bit == 1:
                        status_text.append("RS译码错误")
                    else:
                        status_text.append("RS译码无效")

                # 当LDPC译码开启时（Bit4=1），检查LDPC译码状态
                if bit4_value == 1:
                    ldpc_status_byte = (frame_check_result >> 24) & 0xFF  # 获取Byte0
                    if ldpc_status_byte == 0x00:
                        status_text.append("LDPC译码正确")
                    elif ldpc_status_byte == 0x01:
                        status_text.append("LDPC译码失败")
                    elif ldpc_status_byte == 0x02:
                        status_text.append("帧校验开且帧校验错误")
                    else:
                        # 直接在状态文本中显示具体状态值
                        ldpc_info = f"LDPC译码无效(0x{ldpc_status_byte:02X})"
                        status_text.append(ldpc_info)

            # 如果没有任何映射值，显示原始状态值
            if not status_text:
                status_desc = f"未知译码状态(0x{frame_check_decode:02X}, Bit0={bit0_value}, Bit4={bit4_value})"
                status_text.append(status_desc)

            status_item = QTableWidgetItem(", ".join(status_text))
            self.raw_data_table.setItem(i, 3, status_item)
            
            # 为错误帧添加红色背景，方便识别
            is_error = False
            
            # RS译码错误
            if bit0_value == 1 and ((frame_check_result >> 24) & 0x01) == 1:
                is_error = True
                
            # LDPC译码失败
            if bit4_value == 1:
                ldpc_status = (frame_check_result >> 24) & 0xFF
                if ldpc_status == 0x01 or ldpc_status == 0x02:
                    is_error = True
            
            # 设置错误帧的背景色
            if is_error:
                for col in range(4):
                    item = self.raw_data_table.item(i, col)
                    if item:
                        item.setBackground(Qt.red)
                        item.setForeground(Qt.white)

            # 为空闲帧添加灰色背景
            if frame['virtual_channel'] == 0x3F:
                for col in range(4):
                    item = self.raw_data_table.item(i, col)
                    if item:
                        item.setBackground(Qt.lightGray)
        
        # 调整表格列宽
        self.raw_data_table.resizeColumnsToContents()
        
    def set_continuity_info(self, continuity_info):
        """设置帧计数连续性信息"""
        self.continuity_info = continuity_info
        self.continuity_current_page = 1
        self._update_continuity_pagination()
        self._update_continuity_table()
        
    def _update_continuity_pagination(self):
        """更新连续性统计表格的分页信息"""
        if not self.continuity_info or not self.continuity_info.get('discontinuous_frames'):
            self.continuity_total_pages = 1
            self.continuity_page_info_label.setText("第 1 / 1 页 (无不连续帧)")
            self.continuity_prev_page_btn.setEnabled(False)
            self.continuity_next_page_btn.setEnabled(False)
            return
            
        total_items = len(self.continuity_info['discontinuous_frames'])
        self.continuity_total_pages = (total_items + self.continuity_page_size - 1) // self.continuity_page_size
        
        if self.continuity_total_pages == 0:
            self.continuity_total_pages = 1
            
        # 确保当前页在有效范围内
        if self.continuity_current_page > self.continuity_total_pages:
            self.continuity_current_page = 1
            
        # 更新页码信息显示
        self._update_continuity_pagination_controls()
        
    def _update_continuity_pagination_controls(self):
        """更新连续性统计表格的分页控件状态"""
        total_gaps = self.continuity_info.get('total_gaps', 0) if self.continuity_info else 0
        ratio = self.continuity_info.get('continuous_ratio', 100.0) if self.continuity_info else 100.0
        
        self.continuity_page_info_label.setText(
            f"第 {self.continuity_current_page} / {self.continuity_total_pages} 页 "
            f"(连续性: {ratio:.2f}%, 不连续: {total_gaps}处)"
        )
        self.continuity_prev_page_btn.setEnabled(self.continuity_current_page > 1)
        self.continuity_next_page_btn.setEnabled(self.continuity_current_page < self.continuity_total_pages)
        
    def _on_continuity_page_size_changed(self, text):
        """处理连续性统计表格每页显示数量变化"""
        try:
            self.continuity_page_size = int(text)
            self.continuity_current_page = 1  # 重置到第一页
            self._update_continuity_pagination()
            self._update_continuity_table()
        except ValueError:
            pass  # 忽略无效输入
            
    def _on_continuity_prev_page(self):
        """连续性统计表格前一页按钮点击处理"""
        if self.continuity_current_page > 1:
            self.continuity_current_page -= 1
            self._update_continuity_pagination_controls()
            self._update_continuity_table()
            
    def _on_continuity_next_page(self):
        """连续性统计表格下一页按钮点击处理"""
        if self.continuity_current_page < self.continuity_total_pages:
            self.continuity_current_page += 1
            self._update_continuity_pagination_controls()
            self._update_continuity_table()
            
    def _update_continuity_table(self):
        """更新连续性统计表格显示当前页的数据"""
        # 清空表格
        self.continuity_table.setRowCount(0)
        
        if not self.continuity_info or not self.continuity_info.get('discontinuous_frames'):
            # 如果没有不连续的帧，显示一行提示信息
            self.continuity_table.setRowCount(1)
            self.continuity_table.setItem(0, 0, QTableWidgetItem("无"))
            self.continuity_table.setItem(0, 1, QTableWidgetItem("所有帧均连续"))
            self.continuity_table.setItem(0, 2, QTableWidgetItem("-"))
            self.continuity_table.setItem(0, 3, QTableWidgetItem("-"))
            self.continuity_table.setItem(0, 4, QTableWidgetItem("-"))
            # 设置居中对齐
            for col in range(5):
                item = self.continuity_table.item(0, col)
                if item:
                    item.setTextAlignment(Qt.AlignCenter)
            return
            
        # 计算当前页显示的范围
        discontinuous_frames = self.continuity_info['discontinuous_frames']
        start_idx = (self.continuity_current_page - 1) * self.continuity_page_size
        end_idx = min(start_idx + self.continuity_page_size, len(discontinuous_frames))
        
        # 获取当前页要显示的数据
        display_items = discontinuous_frames[start_idx:end_idx]
        
        # 设置表格行数
        self.continuity_table.setRowCount(len(display_items))
        
        # 填充表格数据
        for i, gap in enumerate(display_items):
            # 位置索引
            self.continuity_table.setItem(i, 0, QTableWidgetItem(str(gap['index'])))
            
            # 前一帧计数（十六进制） - 虚拟信道帧计数为3字节
            prev_hex = format_vc_frame_count(gap['previous_count'])
            self.continuity_table.setItem(i, 1, QTableWidgetItem(prev_hex))
            
            # 当前帧计数（十六进制） - 虚拟信道帧计数为3字节
            curr_hex = format_vc_frame_count(gap['current_count'])
            self.continuity_table.setItem(i, 2, QTableWidgetItem(curr_hex))
            
            # 期望帧计数（十六进制） - 虚拟信道帧计数为3字节
            expected_hex = format_vc_frame_count(gap['expected_count'])
            self.continuity_table.setItem(i, 3, QTableWidgetItem(expected_hex))
            
            # 虚拟信道
            self.continuity_table.setItem(i, 4, QTableWidgetItem(f"VC{gap['virtual_channel']}"))
            
        # 调整表格列宽
        self.continuity_table.resizeColumnsToContents()